home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
filesyst
/
thsfs.tgz
/
thsfs.tar
/
thsfs
/
transfer.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-04
|
6KB
|
349 lines
/*************************************************************
* *
* ths Filesystem 04.10.94 V1.1 *
* *
* Thomas Scheuermann ths@ai-lab.fh-furtwangen.de *
* *
*************************************************************/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/mm.h>
#include <linux/locks.h>
#include <linux/fs.h>
#include <linux/malloc.h>
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/bitops.h>
#include "ths.h"
#include "ths_i.h"
/*
* Lesen eines bestimmten Sektors
*/
int ths_read_sektor(struct super_block *s, unsigned long sektor, struct ths_buffer *tbf)
{
int i,j;
unsigned char *data,*data1=NULL;
struct ths_sb_info *ths_sb;
struct buffer_head *bh;
#ifdef DEBUG
printk("ths_read_sektor : %ld\n",sektor);
#endif
ths_sb = (struct ths_sb_info *)s->u.generic_sbp;
tbf->sektore = 1;
j=0;
if(sektor & 0x01)
j = 512;
tbf->hl[0]=j;
tbf->dirty=0;
if(!(tbf->data[0]=(unsigned char *)kmalloc(512,GFP_KERNEL)))
{
printk("No Memory left !\n");
return -1;
}
/*
* Datenumsetzung
*/
switch(ths_sb->art)
{
case 0:
if(!(bh = bread(s->s_dev,sektor>>1,BLOCK_SIZE)))
{
printk("bread-Fehler\n");
return -1;
}
tbf->bnr[0] = sektor>>1;
data1 = &bh->b_data[j];
break;
case 1:
data1 = ths_uread(s,sektor,&bh);
break;
}
tbf->sektnr[0] = sektor;
tbf->cluster=0;
data = tbf->data[0];
for(i=0;i<512;i++)
{
data[i] = data1[i];
}
brelse(bh);
return 0;
}
/*
* Speicher freigeben nach dem Lesen eines Sektors
*/
void ths_free_sektor(struct ths_buffer *tbf)
{
#ifdef DEBUG
printk("ths_free_sektor : 0x%lx\n",tbf->sektnr[0]);
#endif
if(tbf->dirty != 0)
printk("read-only\n");
kfree_s(tbf->data[0],512);
tbf->data[0]=NULL;
tbf->dirty=0;
tbf->sektore=0;
tbf->hl[0]=0;
}
/*
* Lesen eines Clusters
*/
int ths_read_cluster(struct super_block *s, unsigned short cluster, long offset, struct ths_buffer *tbf)
{
unsigned char *data,*data1=NULL;
int i,j,k;
unsigned short cl1,cl2;
long sektor=0,tmp=0;
struct ths_sb_info *ths_sb;
struct buffer_head *bh;
#ifdef DEBUG
printk("ths_read_cluster : %d bei %ld",cluster,offset);
#endif
ths_sb = (struct ths_sb_info *)s->u.generic_sbp;
tbf->sektore = ths_sb->SektorenProCluster;
tbf->dirty = 0;
j = offset/(ths_sb->SektorenProCluster * 512);
cl1 = cluster;
for(i=0;i<j;i++)
{
cl2 = (ths_sb->fat[cl1/2048])[cl1%2048];
cl1 = cl2;
}
tbf->cluster = cl1;
#ifdef DEBUG
printk(" = Cluster %d\n",cl1);
#endif
switch(ths_sb->art)
{
case 0:
sektor = (long)ths_sb->DatenStart;
sektor += (cl1-2) * ths_sb->SektorenProCluster;
break;
case 1:
tmp = dblsektor(s,cl1);
sektor = (tmp & 0x1fffff)+1;
break;
}
#ifdef DEBUG
printk("sektor : %ld\n",sektor);
#endif
for(i=0;i<tbf->sektore;i++)
{
if(!(tbf->data[i]=(unsigned char *)kmalloc(512,GFP_KERNEL)))
{
printk("No Memory left !\n");
return -1;
}
}
switch(ths_sb->art)
{
case 0:
for(i=0;i<tbf->sektore;i++)
{
if(!(bh = bread(s->s_dev,(sektor+i)>>1,BLOCK_SIZE)))
{
printk("bread-Fehler\n");
return -1;
}
j=0;
if((sektor+i) & 0x01)
j = 512;
data1 = &(bh->b_data[j]);
tbf->bnr[i] = (sektor+i)>>1;
tbf->sektnr[i] = (sektor+i);
data = tbf->data[i];
for(k=0;k<512;k++)
{
data[k] = data1[k];
}
brelse(bh);
}
break;
case 1:
if(tmp & 0x40000000)
{
#ifdef DEBUG
printk("Unkomprimiert\n");
#endif
for(i=0;i<((tmp & 0x3c000000)>>26)+1;i++)
{
data1 = ths_uread(s,sektor+i,&bh);
tbf->bnr[i] = (sektor+i)>>1;
tbf->sektnr[i] = ths_sb->DatenStart+cluster*16+i;
data = tbf->data[i];
for(k=0;k<512;k++)
{
data[k] = data1[k];
}
brelse(bh);
}
}
else
{
#ifdef DEBUG
printk("Komprimiert\n");
#endif
decompress(s,tbf,tmp);
}
break;
}
return 0;
}
/*
* Freigeben des Speichers nach dem Lesen eines Clusters
*/
void ths_free_cluster(struct ths_buffer *tbf)
{
int i;
#ifdef DEBUG
printk("ths_free_cluster : %d\n",tbf->cluster);
#endif
if(tbf->dirty != 0)
printk("read-only\n");
for(i=0;i<tbf->sektore;i++)
{
kfree_s(tbf->data[i],512);
tbf->data[i]=NULL;
tbf->hl[i]=0;
}
tbf->dirty=0;
tbf->sektore=0;
tbf->cluster=0;
}
/*
* ths_uread_sektor liest einen Sektor von dem angegebenen Device.
* Es wird der angegebene Sektor gelesen und ein Zeiger auf den
* Datenpuffer zurueckgegeben. Der belegte Block muss mit brelse(bh)
* wieder freigegeben werden.
*/
char *ths_uread_sektor(long sektor, int dev, struct buffer_head **bh)
{
int i;
#ifdef DEBUG
printk("ths_uread_sektor\n");
#endif
*bh = bread(dev,sektor>>1,BLOCK_SIZE);
i=0;
if(sektor&1)
i=512;
return &((*bh)->b_data[i]);
}
/*
* ths_uread liest einen Sektor aus dem CVF, welcher als offset
* angegeben wird. Der belegte Block muss durch brelse(bh)
* wieder freigegeben werden.
*/
char *ths_uread(struct super_block *s, long offset, struct buffer_head **bh)
{
int i,j;
long sektor;
unsigned short cluster;
struct ths_sb_info *ths_sb;
#ifdef DEBUG
printk("ths_uread : %ld\n",offset);
#endif
ths_sb = (struct ths_sb_info *)s->u.generic_sbp;
cluster = ths_sb->StartCluster;
j=0;
for(i=0;i<offset/ths_sb->uSektorenProCluster;)
{
if(cluster == (ths_sb->cvf[j/2048])[j%2048])
{
j++;
cluster = (ths_sb->cvf[j/2048])[j%2048];
j++;
}
else
{
cluster++;
}
i++;
}
sektor = ths_sb->uDatenStart + (cluster-2)*ths_sb->uSektorenProCluster + (offset % ths_sb->uSektorenProCluster);
#ifdef DEBUG
printk("Sektor : 0x%lx\n",sektor);
#endif
return ths_uread_sektor(sektor,s->s_dev,bh);
}
/*
* dblsektor holt aus der MDFAT-Tabelle den Eintrag
* eines Clusters und gibt ihn zurueck.
*/
long dblsektor(struct super_block *s, unsigned short cluster)
{
struct buffer_head *bh;
struct ths_sb_info *ths_sb;
unsigned char *data,*x;
int i=0;
long cl;
ths_sb = (struct ths_sb_info *)s->u.generic_sbp;
cl = (long)(ths_sb->dcluster + cluster )*4;
data = ths_uread(s,ths_sb->MDFATStart+cl/512,&bh);
x = &data[cl%512];
i= CHL(x);
brelse(bh);
return i;
}